package jnpf.base.controller;

import jnpf.base.entity.*;
import jnpf.base.service.*;
import jnpf.base.vo.DownloadVO;
import jnpf.config.ConfigValueUtil;
import jnpf.constant.MsgCode;
import jnpf.model.login.MenuSelectVO;
import jnpf.util.*;
import jnpf.exception.DataException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jnpf.base.ActionResult;
import jnpf.base.model.module.*;
import jnpf.model.login.UserMenuModel;
import jnpf.util.enums.ModuleTypeEnum;
import jnpf.util.treeutil.ListToTreeUtil;
import jnpf.util.treeutil.SumTree;
import jnpf.util.treeutil.TreeViewModel;
import jnpf.util.treeutil.newtreeutil.TreeDotUtils;
import jnpf.base.vo.ListVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统功能
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Api(tags = "系统菜单", value = "menu")
@RestController
@RequestMapping("/api/system/Menu")
public class ModuleController {

    @Autowired
    private ModuleService moduleService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CacheKeyUtil cacheKeyUtil;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private ConfigValueUtil configValueUtil;
    @Autowired
    private SystemService systemService;


    /**
     * 获取菜单列表
     *
     * @param paginationMenu 分页参数
     * @return ignore
     */
    @ApiOperation("获取菜单列表")
    @GetMapping("/ModuleBySystem/{systemId}")
    public ActionResult<ListVO<MenuListVO>> list(@PathVariable("systemId") String systemId, PaginationMenu paginationMenu) {
        // 获取系统菜单
        List<ModuleEntity> data = moduleService.getList(systemId, paginationMenu.getCategory(), paginationMenu.getKeyword(), null, null, null);
        List<UserMenuModel> list = JsonUtil.getJsonToList(data, UserMenuModel.class);
        List<SumTree<UserMenuModel>> menuList = TreeDotUtils.convertListToTreeDot(list);
        List<MenuListVO> menuvo = JsonUtil.getJsonToList(menuList, MenuListVO.class);
        ListVO vo = new ListVO();
        vo.setList(menuvo);
        return ActionResult.success(vo);
    }

    /**
     * 获取菜单列表(下拉框)
     *
     * @param category 分类
     * @param id       主键
     * @return ignore
     */
    @ApiOperation("获取菜单列表(下拉框)")
    @GetMapping("/Selector/{id}")
    public ActionResult<ListVO<MenuSelectVO>> treeView(String category, @PathVariable("id") String id) {
        String systemId = userProvider.get().getSystemId();
        List<ModuleEntity> data = moduleService.getList(systemId, category, null, "1", "1", null);
        if (!"0".equals(id)) {
            data.remove(moduleService.getInfo(id));
        }
        List<UserMenuModel> list = JsonUtil.getJsonToList(data, UserMenuModel.class);
        List<SumTree<UserMenuModel>> menuList = TreeDotUtils.convertListToTreeDotFilter(list);
        List<MenuSelectVO> menuvo = JsonUtil.getJsonToList(menuList, MenuSelectVO.class);
        ListVO vo = new ListVO();
        vo.setList(menuvo);
        return ActionResult.success(vo);
    }

    /**
     * 通过系统id获取菜单列表(下拉框)
     *
     * @param category 分类
     * @param id       主键
     * @return ignore
     */
    @ApiOperation("通过系统id获取菜单列表(下拉框)")
    @GetMapping("/Selector/{id}/{systemId}")
    public ActionResult<ListVO<MenuSelectAllVO>> treeView(String category, @PathVariable("id") String id, @PathVariable("systemId") String systemId) {
        List<ModuleEntity> data = moduleService.getList(systemId, category, null, "1", "1", null);
        if (!"0".equals(id)) {
            data.remove(moduleService.getInfo(id));
        }
        List<UserMenuModel> list = JsonUtil.getJsonToList(data, UserMenuModel.class);
        if ("0".equals(systemId)) {
            List<SystemEntity> list1 = systemService.getList(null, true);
            list.forEach(t -> {
                if ("-1".equals(t.getParentId())) {
                    t.setParentId(t.getSystemId());
                }
            });
            List<UserMenuModel> jsonToList = JsonUtil.getJsonToList(list1, UserMenuModel.class);
            jsonToList.forEach(t -> {
                t.setType(0);
                t.setParentId("-1");
            });
            list.addAll(jsonToList);
        }
        List<SumTree<UserMenuModel>> menuList = TreeDotUtils.convertListToTreeDotFilter(list);
        List<MenuSelectAllVO> menuvo = JsonUtil.getJsonToList(menuList, MenuSelectAllVO.class);
        ListVO vo = new ListVO();
        vo.setList(menuvo);
        return ActionResult.success(vo);
    }

    /**
     * 获取菜单列表(下拉框)
     *
     * @param category 分类
     * @return ignore
     */
    @ApiOperation("获取菜单列表下拉框")
    @GetMapping("/Selector/All")
    public ActionResult<ListVO<MenuSelectAllVO>> menuSelect(String category) {
        List<ModuleEntity> data = moduleService.getList("0", category, null, null, "1", null);
        List<UserMenuModel> list = JsonUtil.getJsonToList(data, UserMenuModel.class);
//        if ("0".equals(systemId)) {
            List<SystemEntity> list1 = systemService.getList(null, true);
            list.forEach(t -> {
                if ("-1".equals(t.getParentId())) {
                    t.setParentId(t.getSystemId());
                }
            });
            List<UserMenuModel> jsonToList = JsonUtil.getJsonToList(list1, UserMenuModel.class);
            jsonToList.forEach(t -> {
                t.setType(0);
                t.setParentId("-1");
            });
            list.addAll(jsonToList);
//        }
        List<SumTree<UserMenuModel>> menuList = TreeDotUtils.convertListToTreeDotFilter(list);
        List<MenuSelectAllVO> menuvo = JsonUtil.getJsonToList(menuList, MenuSelectAllVO.class);
        ListVO vo = new ListVO();
        vo.setList(menuvo);
        return ActionResult.success(vo);
    }


    /**
     * 系统功能类别树形
     *
     * @return ignore
     */
    @ApiOperation("系统功能类别树形")
    @GetMapping("/{systemId}/TreeView")
    public ActionResult treeView(@PathVariable("systemId") String systemId) {
        List<ModuleEntity> moduleList = moduleService.getList(systemId,null, null, null, null,"0");
        List<TreeViewModel> treeList = new ArrayList<>();
        TreeViewModel treeViewModel = new TreeViewModel();
        treeViewModel.setId("apply");
        treeViewModel.setText("软件开发平台");
        treeViewModel.setParentId("0");
        treeViewModel.setImg("fa fa-windows apply");
        treeList.add(treeViewModel);
        for (ModuleEntity entity : moduleList) {
            TreeViewModel treeModel = new TreeViewModel();
            treeModel.setId(entity.getId());
            treeModel.setText(entity.getFullName());
            treeModel.setParentId("apply");
            treeModel.setImg("fa fa-tags");
            treeList.add(treeModel);
        }
        return ActionResult.success(ListToTreeUtil.toTreeView(treeList));
    }


    /**
     * 获取菜单信息
     *
     * @param id 主键值
     * @return ignore
     * @throws DataException ignore
     */
    @ApiOperation("获取菜单信息")
    @GetMapping("/{id}")
    public ActionResult info(@PathVariable("id") String id) throws DataException {
        ModuleEntity entity = moduleService.getInfo(id);
        ModuleInfoVO vo = JsonUtilEx.getJsonToBeanEx(entity, ModuleInfoVO.class);
        return ActionResult.success(vo);
    }


    /**
     * 新建系统功能
     *
     * @param moduleCrForm 实体对象
     * @return ignore
     */
    @ApiOperation("新建系统功能")
    @PostMapping
    public ActionResult create(@RequestBody @Valid ModuleCrForm moduleCrForm) {
        ModuleEntity entity = JsonUtil.getJsonToBean(moduleCrForm, ModuleEntity.class);
        if (entity.getUrlAddress() != null) {
            entity.setUrlAddress(entity.getUrlAddress().trim());
        }
        if (moduleService.isExistByFullName(entity, moduleCrForm.getCategory(), moduleCrForm.getSystemId())) {
            return ActionResult.fail(MsgCode.EXIST001.get());
        }
        if (moduleService.isExistByEnCode(entity, moduleCrForm.getCategory(), moduleCrForm.getSystemId())) {
            return ActionResult.fail(MsgCode.EXIST002.get());
        }
        moduleService.create(entity);
        return ActionResult.success(MsgCode.SU001.get());
    }

    /**
     * 更新系统功能
     *
     * @param id           主键值
     * @param moduleUpForm 实体对象
     * @return ignore
     */
    @ApiOperation("更新系统功能")
    @PutMapping("/{id}")
    public ActionResult update(@PathVariable("id") String id, @RequestBody @Valid ModuleUpForm moduleUpForm) {
        ModuleEntity entity = JsonUtil.getJsonToBean(moduleUpForm, ModuleEntity.class);
        //判断如果是目录则不能修改类型
        ModuleEntity moduleEntity = moduleService.getInfo(id);
        if (moduleEntity != null && moduleEntity.getType() == 1 && entity.getType() != 1 && moduleService.getList(moduleEntity.getId()).size() > 0) {
            return ActionResult.fail("当前目录存在数据,不能修改类型");
        }
        entity.setId(id);
        if (entity.getUrlAddress() != null) {
            entity.setUrlAddress(entity.getUrlAddress().trim());
        }
        if (moduleService.isExistByFullName(entity, moduleUpForm.getCategory(), moduleUpForm.getSystemId())) {
            return ActionResult.fail(MsgCode.EXIST001.get());
        }
        if (moduleService.isExistByEnCode(entity, moduleUpForm.getCategory(), moduleUpForm.getSystemId())) {
            return ActionResult.fail(MsgCode.EXIST002.get());
        }
        boolean flag = moduleService.update(id, entity);
        if (!flag) {
            return ActionResult.fail(MsgCode.FA002.get());
        }
        return ActionResult.success(MsgCode.SU004.get());
    }

    /**
     * 删除系统功能
     *
     * @param id 主键值
     * @return ignore
     */
    @ApiOperation("删除系统功能")
    @DeleteMapping("/{id}")
    public ActionResult delete(@PathVariable("id") String id) {
        ModuleEntity entity = moduleService.getInfo(id);
        if (entity != null) {
            List<ModuleEntity> list = moduleService.getList().stream().filter(t -> t.getParentId().equals(entity.getId())).collect(Collectors.toList());
            if (list.size() > 0) {
                return ActionResult.fail("删除失败，请先删除子菜单。");
            }
            moduleService.delete(entity);
            return ActionResult.success(MsgCode.SU003.get());
        }
        return ActionResult.fail(MsgCode.FA003.get());
    }

    /**
     * 更新菜单状态
     *
     * @param id 主键值
     * @return ignore
     */
    @ApiOperation("更新菜单状态")
    @PutMapping("/{id}/Actions/State")
    public ActionResult upState(@PathVariable("id") String id) {
        ModuleEntity entity = moduleService.getInfo(id);
        if (entity != null) {
            if (entity.getEnabledMark() == null || "1".equals(String.valueOf(entity.getEnabledMark()))) {
                entity.setEnabledMark(0);
            } else {
                entity.setEnabledMark(1);
            }
            moduleService.update(id, entity);
            //清除redis权限
            String cacheKey = cacheKeyUtil.getUserAuthorize() + userProvider.get().getUserId();
            if (redisUtil.exists(cacheKey)) {
                redisUtil.remove(cacheKey);
            }
            return ActionResult.success(MsgCode.SU004.get());
        }
        return ActionResult.fail(MsgCode.FA002.get());
    }

    /**
     * 系统菜单导出功能
     *
     * @param id 接口id
     * @return ignore
     */
    @ApiOperation("导出系统菜单数据")
    @GetMapping("/{id}/Action/Export")
    public ActionResult exportFile(@PathVariable("id") String id) {
        DownloadVO downloadVO = moduleService.exportData(id);
        return ActionResult.success(downloadVO);
    }

    /**
     * 系统菜单导入功能
     *
     * @param multipartFile 文件
     * @return ignore
     */
    @ApiOperation("系统菜单导入功能")
    @PostMapping(value = "/{systemId}/Action/Import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ActionResult importFile(@PathVariable("systemId") String systemId,
                                   @RequestPart("file") MultipartFile multipartFile,
                                   @RequestParam("parentId") String parentId,
                                   @RequestParam("category") String category) throws DataException {
        //判断是否为.bm结尾
        if (FileUtil.existsSuffix(multipartFile, ModuleTypeEnum.SYSTEM_MODULE.getTableName())) {
            return ActionResult.fail(MsgCode.IMP002.get());
        }
        try {
            //读取文件内容
            String fileContent = FileUtil.getFileContent(multipartFile);
            //转model后导入
            ModuleExportModel exportModel = JsonUtil.getJsonToBean(fileContent, ModuleExportModel.class);
            ModuleEntity moduleEntity = exportModel.getModuleEntity();
            if (!category.equals(moduleEntity.getCategory())) {
                return ActionResult.fail("当前导入菜单为" + category.toUpperCase() + "端菜单，请在对应模块下导入！");
            }
            if ("App".equals(moduleEntity.getCategory()) && "-1".equals(parentId)) {
                return ActionResult.fail("请在顶级节点下创建目录后再进行菜单导入");
            }
            // 设置系统id然后重新赋值
            moduleEntity.setSystemId(systemId);
            moduleEntity.setId(null);
            moduleEntity.setParentId(parentId);
            //清空同步菜单记录 避免重复
            moduleEntity.setModuleId(null);
            String enCode = moduleEntity.getEnCode();
            moduleEntity.setEnCode(moduleEntity.getEnCode() + "_" + RandomUtil.getRandomCode());
            if (moduleEntity.getType() == 3) {
                moduleEntity.setUrlAddress(moduleEntity.getUrlAddress().replace(enCode, moduleEntity.getEnCode()));
            }
            if (moduleService.isExistByFullName(moduleEntity, moduleEntity.getCategory(), moduleEntity.getSystemId())
                    // 导入编码相同导致前端路由跳转有问题，暂时取消编码验证，直接替换编码
//                    ||
//                    moduleService.isExistByEnCode(moduleEntity, moduleEntity.getCategory(), moduleEntity.getSystemId())
        ) {
                return ActionResult.fail(MsgCode.IMP003.get());
            }
            exportModel.setModuleEntity(moduleEntity);
            boolean isExists = moduleService.importData(exportModel);
            if (isExists) {
                return ActionResult.fail(MsgCode.IMP003.get());
            }
        } catch (Exception e) {
            throw new DataException(MsgCode.IMP004.get());
        }
        return ActionResult.success(MsgCode.IMP001.get());
    }

}
